package top.jiangqiang.qyblog.common.base.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import top.jiangqiang.qyblog.common.constant.ResponseEnum;
import top.jiangqiang.qyblog.common.exception.JsonException;
import top.jiangqiang.qyblog.common.utils.JSONUtil;

import java.io.Serial;
import java.io.Serializable;

/**
 * 用于封装接口统一响应结果
 *
 * @author JiangQiang
 * @date 2020/10/1 12:32
 */
@Getter
@Slf4j
public final class Result<T> implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;

    @Schema(description = "响应码，200为成功，400为客户端错误，服务端错误为500")
    private final Integer code;

    @Schema(description = "响应信息，操作成功时忽略此信息，操作失败时此信息为错误提示")
    private final String message;

    @Schema(description = "响应数据")
    private final T data;

    /**
     * 操作成功对应的枚举
     */
    private final static ResponseEnum SUCCESS_200 = ResponseEnum.SUCCESS;
    /**
     * 操作失败对应的枚举
     */
    private final static ResponseEnum ERROR_400 = ResponseEnum.ERROR;
    /**
     * 系统内部错误对应的枚举
     */
    private final static ResponseEnum ERROR_500 = ResponseEnum.INTERNAL_SERVER_ERROR;

    public static <T> Result<T> ok() {
        return build(SUCCESS_200.getCode(), SUCCESS_200.getMessage(), null);
    }

    public static <T> Result<T> ok(String message, T data) {
        return build(SUCCESS_200.getCode(), message, data);
    }

    public static <T> Result<T> ok(T data) {
        return build(SUCCESS_200.getCode(), SUCCESS_200.getMessage(), data);
    }

    public static <T> Result<T> error() {
        return build(ERROR_400.getCode(), ERROR_400.getMessage(), null);
    }

    public static <T> Result<T> error(String message) {
        return build(ERROR_400.getCode(), message, null);
    }

    public static <T> Result<T> error(String message, T data) {
        return build(ERROR_400.getCode(), message, data);
    }

    public static <T> Result<T> error(JsonException jsonException) {
        return build(jsonException.getCode(), jsonException.getMessage(), null);
    }

    /**
     * 处理未知异常
     *
     * @param throwable 未知错误，异常
     */
    public static <T> Result<T> error(Throwable throwable) {
        log.debug(ResponseEnum.INTERNAL_SERVER_ERROR.getMessage(), throwable);
        return build(ResponseEnum.INTERNAL_SERVER_ERROR.getCode(), ResponseEnum.INTERNAL_SERVER_ERROR.getMessage(), null);
    }

    public static <T> Result<T> build(ResponseEnum responseEnum) {
        return build(responseEnum.getCode(), responseEnum.getMessage(), null);
    }

    public static <T> Result<T> build(ResponseEnum responseEnum, T data) {
        return build(responseEnum.getCode(), responseEnum.getMessage(), data);
    }

    private static <T> Result<T> build(int code, String message, T data) {
        log.debug("{}：code={}, message={}, data={}", code == SUCCESS_200.getCode() ? "OK" : "ERROR", code, message, JSONUtil.toJsonStr(data));
        return new Result<>(code, message, data);
    }

    private Result(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    @Override
    public String toString() {
        return JSONUtil.toJsonStr(this);
    }

}
